package com.qianxunclub.chapter1.zookeeper;

import org.apache.zookeeper.*;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

public class Main {
    private static ZooKeeper zk_;
    static private Main static_;
    private Main(){}
    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        try {
            String hostports = "120.25.173.32:2181";
            Main main=Main.Instance();
            main.Init(hostports, 1000);

            String str = main.Instance().Get("goods");
            if (str == null || "".equals(str)) {
                zk_.create("/goods", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
            String[] goods = { "iPhone6s", "小米移动电源" };
            for (String g : goods) {
                zk_.create("/goods/" + g, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
            }

            int threadCount = 5;
            CyclicBarrier cb = new CyclicBarrier(threadCount); // 为了更好地表示并发，这里用了CyclicBarrier类
            for (int i = 0; i < threadCount; i++) {
                // 用多线程摸您多用户
                new Thread(new Thread1(cb)).start();
            }
            System.in.read();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    static class Thread1 implements Runnable {
        ZooKeeper zk = null;
        CyclicBarrier cb;

        // 是否还没有抢过商品
        boolean isNotGet = true;

        public Thread1(CyclicBarrier cb) {
            this.cb = cb;
        }

        private void snatchGoods() throws Exception {

            // 获取商品库存
            List<String> goodsList = zk.getChildren("/goods", true);// 获取商品列表并监控变化，如果在和其它用户抢购同一个商品时没抢到的情况下可再次监控其它商品
            if (goodsList.isEmpty()) {
                // 商品库存为空，表示商品抢光了
                System.out.println(Thread.currentThread().getName() + "没抢到商品");
            } else {
                // 获取第一个商品
                String goods = goodsList.get(0);
                try {
                    // 从内存中删除商品节点，表示抢购，如果删除失败，就表示没抢到这个商品，并进入到下面的catch块中
                    zk.delete("/goods/" + goods, -1);
                    // 限制每个用户只能抢购一件商品，设置false表示已经抢购过了
                    isNotGet = false;
                    System.out.println(Thread.currentThread().getName() + "抢到了" + goods);
                } catch (Exception e) {

                }
            }
        }

        @Override
        public void run() {
            try {
                zk = new ZooKeeper("120.25.173.32:2181", 2000, new Watcher() {
                    @Override
                    public void process(WatchedEvent event) {
                        try {
                            EventType type = event.getType();
                            if (isNotGet) {
                                if (type == EventType.None) {
                                    // 用户第一次访问，则立即执行商品的抢购
                                    snatchGoods();
                                } else if (type == EventType.NodeChildrenChanged) {
                                    // 抢购一件商品失败后，再抢购另一件商品
                                    snatchGoods();
                                }
                            }
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    static public Main Instance(){
        if(static_ == null){
            static_ = new Main();
        }
        return static_;
    }
    public static boolean Init(String hostports, int times){
        try{
            CountDownLatch connectedLatch = new CountDownLatch(1);
            Watcher watcher = new ConnectedWatcher(connectedLatch);
            zk_ = new ZooKeeper(hostports, times, watcher);
            waitUntilConnected(zk_, connectedLatch);
        }catch(Exception e){
            System.out.println(e);
            return false;
        }
        return true;
    }
    static class ConnectedWatcher implements Watcher {
        private CountDownLatch connectedLatch;
        ConnectedWatcher(CountDownLatch connectedLatch) {
            this.connectedLatch = connectedLatch;
        }
        @Override
        public void process(WatchedEvent event) {
            if (event.getState() == Event.KeeperState.SyncConnected) {
                connectedLatch.countDown();
            }
        }
    }
    public static void waitUntilConnected(ZooKeeper zooKeeper, CountDownLatch connectedLatch) {
        if (ZooKeeper.States.CONNECTING == zooKeeper.getState()) {
            try {
                connectedLatch.await();
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
        }
    }

    public String Get(String keys){
        String re = "";
        String ppath = "";
        int oldpos = -1;
        int pos = 0;
        while(true){
            pos = keys.indexOf(".", oldpos + 1);
            if(pos < 0){
                ppath += "/";
                String str = keys.substring(oldpos + 1);
                ppath += str;
                break;
            }
            ppath += "/";
            String str = keys.substring(oldpos + 1,  pos);
            ppath += str;
            oldpos = pos;
        }
        Stat stat = new Stat();
        try{
            byte[] b = zk_.getData(ppath, false, stat);    //获取节点的信息及存储的数据
            re = new String(b);
        }
        catch(Exception e){
            System.out.println(e);
        }
        return re;
    }

}
